/*
 * ANNOTATED AND DOCUMENTED BY Eduardo Sobrino
 * -----------------------------------------------------------------------------
 * Project    : General LDAP User Support (UNIX + Windows)
 * Contents   : Provide a class that define and implements a general support for
 *            : LDAP User.
 * Depends    : UNMANAGED C/C++
 * Compatible : The following code will complie/run on Win32 (Windows) and any
 *            : UNIX platform.
 * File       : LdapUser.cpp
 * Copywright : Open Knowledge (c) 2000-2007
 * Author     : Eduardo Sobrino
 * Date       : Jun/2000
 * Updated    : Aug/2000  (Added support for message queue [WIN32 only])
 */

#include "stdafx.h"
#include "Win32.Net.LdapUser.h"
#include <stdio.h>

// commonly used naming attributes

namespace Kif
{
namespace Win32
{
namespace Net
{
namespace Ldap
{

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::Add(TCHAR *pUserId,TCHAR *pPassword)
 * Purpose  : Add a new user. True is returned if all is ok.
 * In       : pAcct     = account name / number (TCHAR*)
 *          : pUserId   = pointer to user id (can't be NULL) (TCHAR*)
 *          : pPassword = pointer to new password (NULL if none) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::Add(TCHAR *pAcct,TCHAR *pUserId,TCHAR *pPassword)
{
   bool isok ;

   if (pAcct && pUserId && pLdap && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_USER_DN,pUserId,UsersDN.GetBuffer());

      LdifEntries entries(pLdap->psLdap,str);

      entries.AppendToAdd(LDAP_NAMEATTR_ObjectClass,TEXT("user"));
      entries.AppendToAdd(LDAP_NAMEATTR_CN,pUserId);
      entries.AppendToAdd(LDAP_NAMEATTR_SAMAccount,pAcct);
      entries.AppendToAdd(LDAP_NAMEATTR_displayName,pUserId);

      if (pPassword)
         entries.AppendToAdd(LDAP_NAMEATTR_userPassword,pPassword);

      isok = entries.Add();
   }
   else
      isok = false;

   return(isok);
}  // end of add new directory entries...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::SetPassword(TCHAR *pUserId,TCHAR *pNewPassword)
 * Purpose  : Set user password.  'true' is returned if all was ok.
 * In       : pUserId      = pointer to user id (can't be NULL) (TCHAR*)
 *          : pNewPassword = pointer to new password (NULL if none) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::SetPassword(TCHAR *pUserId,TCHAR *pNewPassword)
{
   bool isok ;

   if (pUserId && pLdap && pNewPassword && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_USER_DN,pUserId,UsersDN.GetBuffer());

      LdifEntries entries(pLdap->psLdap,str);

      if (pNewPassword)
         entries.AppendToUpdate(LDAP_NAMEATTR_userPassword,pNewPassword);

      isok = entries.Update();
   }
   else
      isok = false;

   return(isok);
}  // end of set user password...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::UpdateAccount(TCHAR *pAcct,TCHAR *pUserId,
 *          :    TCHAR *pNewPassword)
 * Purpose  : Set user id and password of given account. 'true' is returned if
 *          : all was ok.
 * In       : pAcct        = account to update (TCHAR*)
 *          : pUserId      = pointer to user id (can't be NULL) (TCHAR*)
 *          : pNewPassword = pointer to new password (NULL if none) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::UpdateAccount(TCHAR *pAcct,TCHAR *pUserId,TCHAR *pNewPassword)
{
   bool isok ;

   if (pAcct && pUserId && pLdap && pNewPassword && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_USER_DN,pUserId,UsersDN.GetBuffer());

      LdifEntries entries(pLdap->psLdap,str);

      if (pNewPassword)
      {
         entries.AppendToUpdate(LDAP_NAMEATTR_SAMAccount,pAcct);
         entries.AppendToUpdate(LDAP_NAMEATTR_userPassword,pNewPassword);
      }

      isok = entries.Update();
   }
   else
      isok = false;

   return(isok);
}  // end of set user password...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::Delete(TCHAR *pUserId)
 * Purpose  : Delete user. True is returned if all is ok.
 * In       : pUserId = pointer to user id (can't be NULL) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::Delete(TCHAR *pUserId)
{
   bool isok;

   if (pUserId && pLdap && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_USER_DN,pUserId,UsersDN.GetBuffer());

      isok = pLdap->DeleteEntry(str);
   }
   else
      isok = false;

   return(isok);
}  // end of delete user directory entry...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::Exists(TCHAR *pUserId)
 * Purpose  : See if user exists. True is returned if found.
 * In       : pUserId = pointer to user id (can't be NULL) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::Exists(TCHAR *pUserId)
{
   bool isok ;

   if (pUserId && pLdap && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_CN,pUserId);

      LdapEntry ent;

      ent.psLdap = pLdap->psLdap;
      ent.NamingContext.Copy(UsersDN.GetBuffer());
      ent.Find(str);

      isok = (!ent.Eof);
      ent.Free();

   }
   else
      isok = false;

   return(isok);
}  // end of see if user exists...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::Find(TCHAR *pUserId,TCHAR *pAttr,
 *          :    TCHAR *pValue,int iValLen)
 * Purpose  : Find user. True is returned if found.
 * In       : pUserId = pointer to user id (can't be NULL) (TCHAR*)
 *          : pAttr   = attribute to find (TCHAR*)
 * Out      : pValue  = pointer to value found (TCHAR*)
 * In       : iValLen = maximum value length (int)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::Find(TCHAR *pUserId,TCHAR *pAttr,TCHAR *pValue,int iValLen)
{
   bool isok = false ;

   if (pUserId && pLdap && (UsersDN.GetLength() > 0))
   {
      TCHAR str[Kif::Win32::String::MaxStringLength+1];
      _stprintf_s(str,Kif::Win32::String::MaxStringLength,
         LDAP_TEMPLATE_CN,pUserId);

      LdapEntry ent;

      ent.psLdap = pLdap->psLdap;
      ent.NamingContext.Copy(UsersDN);
      ent.Find(str,LDAP_SCOPE_BASE,TEXT("objectclass=user"),pAttr);

      while (!ent.Eof)
      {
         if (!Kif::Win32::String::Compare(pAttr,ent.pEntryName))
         {
            int iLen = Kif::Win32::String::GetLength(ent.pEntryValue);
            if (iLen > iValLen)
               iLen = iValLen;
            Kif::Win32::String::Copy(pValue,iLen,ent.pEntryValue);
            pValue[iLen] = NULL;
            isok = true;
            break;
         }
         ent.Next();
      }
      ent.Free();
   }

   return(isok);
}  // end of add new directory entries...

/*
 * -----------------------------------------------------------------------------
 * Function : LdapUser::Authenticate(TCHAR *pUserId,TCHAR *pNewPassword)
 * Purpose  : Find user. True is returned if found.
 * In       : pUserId   = pointer to user id (can't be NULL) (TCHAR*)
 *          : pPassword = pointer to new password (NULL if none) (TCHAR*)
 * Date     : Jun/2000  (ESob)
 */

bool LdapUser::Authenticate(TCHAR *pUserId,TCHAR *pPassword)
{
   bool isok = false ;

   if (pUserId && pLdap)
   {
      TCHAR Pwd[Kif::Win32::String::MaxStringLength+1];
      Find(pUserId,
         LDAP_NAMEATTR_userPassword,Pwd,Kif::Win32::String::MaxStringLength);
      isok = (!Kif::Win32::String::Compare(Pwd,pPassword));
   }

   return(isok);
}  // end of add new directory entries...

// -----------------------------------------------------------------------------

}  // end of Kif::Win32::Net::Ldap
}  // end of Kif::Win32::Net
}  // end of Kif::Win32
}  // end of Kif
